/***************************************************************************
                            gui.c  -  description
                             -------------------
    begin             : 08.04.2008
    copyright         : (C) 2008 by MHS-Elektronik GmbH & Co. KG, Germany
    autho             : Klaus Demlehner, klaus@mhs-elektronik.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software, you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License           *
 *   version 2.1 as published by the Free Software Foundation.             *
 *                                                                         *
 ***************************************************************************/
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include "main.h"
#include "octopus.h"
#include "dialogs.h"
#include "giwled.h"
#include "paths.h"
#include "gtk_util.h"
#include "abaut_dlg.h"
#include "std_op.h"
#include "ain_op.h"
#include "setup.h"
#include "file_sel.h"
#include "gui.h"


struct TExtraSetup
  {
  GtkWidget *BoxWidget;
  GtkWidget *PwmSpeed1Widget;
  GtkWidget *PwmSpeed2Widget;
  GtkWidget *AdRefWidget;
  };

struct TExtraSetup ExtraSetup;
struct TConfig Config;
guint RefreshTimerId; 

const struct TAbautTxt AbautTxt = {
  .Programm =   "Octopus-GUI",
  .LogoFile =   NULL,
  .Version =    "Version: 1.10",
  .Copyright =  "Copyright (C) 2008 MHS-Elektronik GmbH + Co. KG, Germany",
  .Autor =      "Klaus Demlehner",
  .Email =      "klaus@mhs-elektronik.de",
  .Homepage =   "www.MHS-Elektronik.de",
  .ShortLizenz = "This Programm comes with ABSOLUTELY NO WARRANTY; for details type \"GNU Licence\".\n" \
     "This is free software, and you are welcomme to redistribute it under certain\n" \
     "conditions; type \"GNU Licence\" for details",
  .LizenzFile = "COPYING"};


// Main.c
int OctopusSetIoConfig(void);

const struct TIoPinDefs IoPinDefs[] = {
  { 1, PIN_IN_OUT, 19, 3,  "Pin 1",  "In 1",  "Out 1", ""},
  { 2, PIN_IN_OUT, 18, 3,  "Pin 2",  "In 2",  "Out 2", ""},
  { 3, PIN_IN_OUT, 17, 3,  "Pin 3",  "In 3",  "Out 3", ""},
  { 4, PIN_IN_OUT, 16, 3,  "Pin 4",  "In 4",  "Out 4", ""},
  { 5, PIN_IN_OUT, 15, 3,  "Pin 5",  "In 5",  "Out 5", ""},
  { 6, PIN_IN_OUT, 14, 3,  "Pin 6",  "In 6",  "Out 6", ""},
  { 7, PIN_IN_OUT, 13, 3,  "Pin 7",  "In 7",  "7", ""},
  { 8, PIN_IN_OUT | PIN_A_OUT, 12, 3,  "Pin 8",  "In 8",  "Out 8", "PWM 2"},  
  { 9, PIN_IN_OUT | PIN_A_OUT, 11, 3,  "Pin 9",  "In 9",  "Out 9", "PWM 1"},
  {10, PIN_IN_OUT, 10, 3, "Pin 10", "In 10", "In 10", ""},
  {11, PIN_IN_OUT,  9, 3, "Pin 11", "In 11", "Out 11", ""},
  {12, PIN_IN_OUT,  8, 3, "Pin 12", "In 12", "Out 12", ""},
  {13, PIN_IN_OUT,  7, 3, "Pin 13", "In 13", "Out 13", ""},
  {14, PIN_IN_OUT,  6, 3, "Pin 14", "In 14", "Out 14", ""},
  {15, PIN_IN_OUT,  5, 3, "Pin 15", "In 15", "Out 15", ""},
  {16, PIN_IN_OUT,  4, 3, "Pin 16", "In 16", "Out 16", ""},
  {17, PIN_IN_OUT,  3, 3, "Pin 17", "In 17", "Out 17", ""},
  {18, PIN_IN_OUT,  2, 3, "Pin 18", "In 18", "Out 18", ""},
  {19, PIN_IN_OUT,  1, 3, "Pin 19", "In 19", "Out 19", ""},
  {26, PIN_IN_OUT,  1, 1, "Pin 24", "In 24", "Out 24", ""},
  {27, PIN_IN_OUT,  2, 1, "Pin 25", "In 25", "Out 25", ""},
  {28, PIN_IN_OUT,  3, 1, "Pin 26", "In 26", "Out 26", ""},
  {29, PIN_IN_OUT,  4, 1, "Pin 27", "In 27", "Out 27", ""},
  {30, PIN_IN_OUT,  5, 1, "Pin 28", "In 28", "Out 28", ""},
  {31, PIN_IN_OUT,  6, 1, "Pin 29", "In 29", "Out 29", ""},
  {32, PIN_IN_OUT,  7, 1, "Pin 30", "In 30", "Out 30", ""},
  {33, PIN_IN_OUT | PIN_A_IN | PIN_A_IN_DIF, 8, 1, "Pin 31", "In 31", "Out 31", "AD 7"},
  {34, PIN_IN_OUT | PIN_A_IN,  9, 1, "Pin 32", "In 32", "Out 32", "AD 6"},
  {35, PIN_IN_OUT | PIN_A_IN | PIN_A_IN_DIF, 10, 1, "Pin 33", "In 33", "Out 33", "AD 5"},
  {36, PIN_IN_OUT | PIN_A_IN, 11, 1, "Pin 34", "In 34", "Out 34", "AD 4"},
  {37, PIN_IN_OUT | PIN_A_IN | PIN_A_IN_DIF, 12, 1, "Pin 35", "In 35", "Out 35", "AD 3"},
  {38, PIN_IN_OUT | PIN_A_IN, 13, 1, "Pin 36", "In 36", "Out 36", "AD 2"},
  {39, PIN_IN_OUT | PIN_A_IN | PIN_A_IN_DIF, 14, 1, "Pin 37", "In 37", "Out 37", "AD 1"},
  {40, PIN_IN_OUT | PIN_A_IN, 15, 1, "Pin 38", "In 38", "Out 38", "AD 0"},
  {41, PIN_IN_OUT, 16, 1, "Pin 39", "In 39", "Out 39", ""},
  {42, PIN_IN_OUT, 17, 1, "Pin 40", "In 40", "Out 40", ""},
  {43, PIN_IN_OUT, 18, 1, "Pin 41", "In 41", "Out 41", ""},
  {44, PIN_IN_OUT, 19, 1, "Pin 42", "In 42", "Out 42", ""}};
  

struct TIoPin IoPin[IO_PIN_COUNT];
GtkWidget *TableWdg;
char *CfgFileName = NULL;


void OptionChangeCB(GtkButton *button, gpointer user_data);


void GuiInit(void)
{
int i;

for (i = 0; i < IO_PIN_COUNT; i++)
  {
  IoPin[i].Mode = 0;
  IoPin[i].Name = NULL;
  IoPin[i].In = 0;
  IoPin[i].AIn = 0;
  IoPin[i].OutWidget = NULL;
  IoPin[i].InBoxWidget = NULL;
  IoPin[i].InWidget = NULL;
  IoPin[i].AInBoxWidget = NULL;
  IoPin[i].AInWidget = NULL;
  IoPin[i].AOutBoxWidget = NULL;
  IoPin[i].AOutWidget = NULL;
  IoPin[i].ConfigBoxWidget = NULL;
  IoPin[i].ConfigWidget = NULL;
  IoPin[i].InNameWidget = NULL;
  IoPin[i].AInNameWidget = NULL;
  IoPin[i].AOutNameWidget = NULL;
  IoPinSetDefaultName(i);
  }
Config.AdRef = 1;
Config.PwmSpeed1 = 1;
Config.PwmSpeed2 = 1;
}


void GuiDestroy(void)
{
int i;

for (i = 0; i < IO_PIN_COUNT; i++)
  {  
  save_free(IoPin[i].Name);
  StdOpDlgDestroy(&StdOpDlg);
  AInOpDlgDestroy(&AInOpDlg);
  }
}


void IoPinSetDefaultName(int pin_idx)
{
struct TIoPin *io_pin;

io_pin = &IoPin[pin_idx];
save_free(io_pin->Name);
if (io_pin->Mode == 0)
  io_pin->Name = g_strdup(IoPinDefs[pin_idx].InName);
else if (io_pin->Mode == 1)
  io_pin->Name = g_strdup(IoPinDefs[pin_idx].OutName);
else
  io_pin->Name = g_strdup(IoPinDefs[pin_idx].AnalogName);
}


void OptionChangeCB(GtkButton *button, gpointer user_data)
{
unsigned int index;

index = (unsigned int)user_data;
GetConfigForPin(index);
switch (IoPin[index].Mode)
  {
  case 0 :   // 0 = Input
  case 1 :   // 1 = Output
  case 2 : { // 2 = Analog Output
           StdOpDlgExecute(index);
           break;
           }
  case 3 :   // 3 = Analog Input 
  case 4 : { // 4 = Analog Differential +  
           AInOpDlgExecute(index);
           break;
           }
  case 5 : { // 5 = Analog Differential -
           break;
           }
  }
}


void OutChangeProc(GtkCheckButton *button, gpointer user_data)
{
int index, pin, state;

index = (int)user_data;
g_assert((index >= 0) && (index < IO_PIN_COUNT));
pin = IoPinDefs[index].Pin;
if ((!(IoPinDefs[index].Flags & PIN_OUT)) || (IoPin[index].Mode != 1))
  return;
if (GTK_TOGGLE_BUTTON(button)->active == TRUE)   
  state = 1;
else
  state = 0;
if (octopus_io_set_pin (&Octopus, pin, state) < 0)
  msg_box(MSG_TYPE_ERROR, "Error", "ERROR (PIN:%u) octopus_io_set_pin: %s", pin, Octopus.error_str);            
}


void AOutChangeProc(GtkSpinButton *spinbutton, gpointer user_data)
{
unsigned char value;
int index, pin;

index = (int)user_data;
g_assert((index >= 0) && (index < IO_PIN_COUNT));
pin = IoPinDefs[index].Pin;
if ((!(IoPinDefs[index].Flags & PIN_A_OUT)) || (IoPin[index].Mode != 2))
  return;  
//gtk_spin_button_update(GTK_SPIN_BUTTON(spinbutton));
value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinbutton));  
if (octopus_pwm_value(&Octopus, pin, value) < 0)
  msg_box(MSG_TYPE_ERROR, "Error", "ERROR (PIN:%u) octopus_pwm_value: %s", pin, Octopus.error_str);
}


void SetAllOutputs(int state)
{
int i;
gboolean s;
GtkWidget *widget;

if (state)
  s = TRUE;
else
  s = FALSE;
for (i = 0; i < IO_PIN_COUNT; i++)
  {
  widget = IoPin[i].OutWidget;
  if (widget)
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s);
  }
}



void on_open_activate(GtkMenuItem *menuitem, gpointer user_data)
{
gchar *file_name;

file_name = g_strdup(CfgFileName);
if (SelectFileDlg("Konfigurationsfile laden", FILE_SELECTION_OPEN, &file_name) > 0)
  {
  if (RefreshTimerId)
    {
    g_source_remove(RefreshTimerId);
    RefreshTimerId = 0;
    }
  if (!LoadConfigFile(file_name))
    {
    save_free(CfgFileName);
    CfgFileName = g_strdup(file_name);
    }
  SetConfigToGui();
  (void)OctopusSetIoConfig();
  SetGuiShowing(0);
  if (!RefreshTimerId)
    RefreshTimerId = g_timeout_add(250, RefreshMainWin, NULL);
  }
save_free(file_name);
}


void on_save_activate(GtkMenuItem *menuitem, gpointer user_data)
{
gchar *file_name;

file_name = g_strdup(CfgFileName);
if (SelectFileDlg("Konfigurationsfile speichern", FILE_SELECTION_SAVE, &file_name) > 0)
  {
  if (!SaveConfigFile(file_name))
    {
    save_free(CfgFileName);
    CfgFileName = g_strdup(file_name);
    }
  }
save_free(file_name);
}


void on_beenden1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
// Programm beenden
gtk_main_quit();
}


void on_about1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
ShowAbautDlg(Paths.base_dir, &AbautTxt);;
}


void on_alle_outputs_0_activate(GtkMenuItem *menuitem, gpointer user_data)
{
SetAllOutputs(0);
}

void on_alle_outputs_1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
SetAllOutputs(1);
}


void on_config1_activate(GtkCheckMenuItem *object, gpointer user_data)
{
if (object->active == TRUE)
  {
  if (RefreshTimerId)
    {
    g_source_remove(RefreshTimerId);
    RefreshTimerId = 0;
    }
  SetGuiShowing(1);
  }
else
  {
  GetConfigFromGui();
  (void)OctopusSetIoConfig();
  SetGuiShowing(0);
  if (!RefreshTimerId)
    RefreshTimerId = g_timeout_add(250, RefreshMainWin, NULL);
  }
}


void GetConfigForPin(int pin_idx)
{
unsigned int mode;

mode = gtk_combo_box_get_active(GTK_COMBO_BOX(IoPin[pin_idx].ConfigWidget));
if (IoPin[pin_idx].Mode != 5)
  {
  if (mode < 2)
    IoPin[pin_idx].Mode = mode;
  else 
    {
    if (IoPinDefs[pin_idx].Flags & PIN_A_OUT)
      IoPin[pin_idx].Mode = mode;
    else
      {
      if (IoPin[pin_idx].Mode < 4)
        IoPin[pin_idx].Mode = mode+1;
      }
    }
  }
}


void GetConfigFromGui(void)
{
int i;

Config.AdRef = gtk_combo_box_get_active(GTK_COMBO_BOX(ExtraSetup.AdRefWidget)) + 1;
Config.PwmSpeed1 = gtk_combo_box_get_active(GTK_COMBO_BOX(ExtraSetup.PwmSpeed1Widget)) + 1;
Config.PwmSpeed2 = gtk_combo_box_get_active(GTK_COMBO_BOX(ExtraSetup.PwmSpeed2Widget)) + 1; 
for (i = 0; i < IO_PIN_COUNT; i++)
  GetConfigForPin(i);
}


void SetConfigToGui(void)
{
int i;
unsigned int mode;

gtk_combo_box_set_active(GTK_COMBO_BOX(ExtraSetup.AdRefWidget), Config.AdRef - 1);
gtk_combo_box_set_active(GTK_COMBO_BOX(ExtraSetup.PwmSpeed1Widget), Config.PwmSpeed1 -1);
gtk_combo_box_set_active(GTK_COMBO_BOX(ExtraSetup.PwmSpeed2Widget), Config.PwmSpeed2 - 1); 
for (i = 0; i < IO_PIN_COUNT; i++)
  {
  mode = IoPin[i].Mode;
  if (mode > 2)
    mode = 2;
  gtk_combo_box_set_active(GTK_COMBO_BOX(IoPin[i].ConfigWidget), mode); 
  }  
}


void SetGuiShowing(int config)
{
int i, mode;

if (ExtraSetup.BoxWidget)
  {
  if (config)
    gtk_widget_show(ExtraSetup.BoxWidget);
  else
    gtk_widget_hide(ExtraSetup.BoxWidget);
  }
for (i = 0; i < IO_PIN_COUNT; i++)
  { 
  if (config)
    mode = 100;
  else
    mode = IoPin[i].Mode;
  switch (mode)
    {
    case 0  : {  // Input              
              if (IoPin[i].OutWidget)
                gtk_widget_hide(IoPin[i].OutWidget);
              if (IoPin[i].InBoxWidget)
                gtk_widget_show(IoPin[i].InBoxWidget);
              if (IoPin[i].AInBoxWidget)
                gtk_widget_hide(IoPin[i].AInBoxWidget);
              if (IoPin[i].AOutBoxWidget)
                gtk_widget_hide(IoPin[i].AOutBoxWidget); 
              if ((IoPin[i].InNameWidget) && (IoPin[i].Name))
                gtk_label_set_text(GTK_LABEL(IoPin[i].InNameWidget), IoPin[i].Name);
              gtk_widget_hide(IoPin[i].ConfigBoxWidget);
              break;
              }
    case 1  : {  // Output
              if (IoPin[i].OutWidget)
                {
                if (IoPin[i].Name)
                  gtk_button_set_label(GTK_BUTTON(IoPin[i].OutWidget), IoPin[i].Name);
                gtk_widget_show(IoPin[i].OutWidget);
                }
              if (IoPin[i].InBoxWidget)
                gtk_widget_hide(IoPin[i].InBoxWidget);
              if (IoPin[i].AInBoxWidget)
                gtk_widget_hide(IoPin[i].AInBoxWidget);
              if (IoPin[i].AOutBoxWidget)
                gtk_widget_hide(IoPin[i].AOutBoxWidget); 

              gtk_widget_hide(IoPin[i].ConfigBoxWidget);
              break;
              }                                                 
    case 2  : {  // 2 = Analog Output
              if (IoPin[i].OutWidget)
                gtk_widget_hide(IoPin[i].OutWidget);
              if (IoPin[i].InBoxWidget)
                gtk_widget_hide(IoPin[i].InBoxWidget);
              if (IoPin[i].AInBoxWidget)
                gtk_widget_hide(IoPin[i].AInBoxWidget);
              if (IoPin[i].AOutBoxWidget)
                gtk_widget_show(IoPin[i].AOutBoxWidget);
              if ((IoPin[i].AOutNameWidget) && (IoPin[i].Name))
                gtk_label_set_text(GTK_LABEL(IoPin[i].AOutNameWidget), IoPin[i].Name);
              gtk_widget_hide(IoPin[i].ConfigBoxWidget);
              break;
              }
    case 3  :    // 3 = Analog Input 
    case 4  :    // 4 = Analog Differential +
    case 5  : {  // 5 = Analog Differential -
              if (IoPin[i].OutWidget)
                gtk_widget_hide(IoPin[i].OutWidget);
              if (IoPin[i].InBoxWidget)
                gtk_widget_hide(IoPin[i].InBoxWidget);
              if (IoPin[i].AOutBoxWidget)
                gtk_widget_hide(IoPin[i].AOutBoxWidget);
              if (mode != 5)
                {
                if (IoPin[i].AInBoxWidget)
                  gtk_widget_show(IoPin[i].AInBoxWidget);                
                if ((IoPin[i].AInNameWidget) && (IoPin[i].Name))
                  gtk_label_set_text(GTK_LABEL(IoPin[i].AInNameWidget), IoPin[i].Name);             
                }
              else
                {
                if (IoPin[i].AInBoxWidget)
                  gtk_widget_hide(IoPin[i].AInBoxWidget);
                }
              gtk_widget_hide(IoPin[i].ConfigBoxWidget);
              break;
              }

    default : {  // Config
              if (IoPin[i].OutWidget)
                gtk_widget_hide(IoPin[i].OutWidget);
              if (IoPin[i].InBoxWidget)
                gtk_widget_hide(IoPin[i].InBoxWidget);
              if (IoPin[i].AInBoxWidget)
                gtk_widget_hide(IoPin[i].AInBoxWidget);
              if (IoPin[i].AOutBoxWidget)
                gtk_widget_hide(IoPin[i].AOutBoxWidget);             
              gtk_widget_show(IoPin[i].ConfigBoxWidget);
              break;
              }
    }    
  }
}


gint RefreshMainWin(gpointer data)
{
int i, value;
unsigned char b;
char str[20];

b = octopus_io_get_port(&Octopus, 1); 
if (b & 0x01) IoPin[3].In = 1; else IoPin[3].In = 0;
if (b & 0x02) IoPin[4].In = 1; else IoPin[4].In = 0;
if (b & 0x04) IoPin[5].In = 1; else IoPin[5].In = 0;
if (b & 0x08) IoPin[6].In = 1; else IoPin[6].In = 0;
if (b & 0x10) IoPin[7].In = 1; else IoPin[7].In = 0;
if (b & 0x20) IoPin[8].In = 1; else IoPin[8].In = 0;
if (b & 0x40) IoPin[9].In = 1; else IoPin[9].In = 0;
if (b & 0x80) IoPin[10].In = 1; else IoPin[10].In = 0;

b = octopus_io_get_port(&Octopus, 2); 
if (b & 0x01) IoPin[19].In = 1; else IoPin[19].In = 0;
if (b & 0x02) IoPin[20].In = 1; else IoPin[20].In = 0;
if (b & 0x04) IoPin[21].In = 1; else IoPin[21].In = 0;
if (b & 0x08) IoPin[22].In = 1; else IoPin[22].In = 0;
if (b & 0x10) IoPin[23].In = 1; else IoPin[23].In = 0;
if (b & 0x20) IoPin[24].In = 1; else IoPin[24].In = 0;
if (b & 0x40) IoPin[25].In = 1; else IoPin[25].In = 0;

b = octopus_io_get_port(&Octopus, 3);
if (b & 0x01) IoPin[11].In = 1; else IoPin[11].In = 0;
if (b & 0x02) IoPin[12].In = 1; else IoPin[12].In = 0;
if (b & 0x04) IoPin[13].In = 1; else IoPin[13].In = 0;
if (b & 0x08) IoPin[14].In = 1; else IoPin[14].In = 0;
if (b & 0x10) IoPin[15].In = 1; else IoPin[15].In = 0;
if (b & 0x20) IoPin[16].In = 1; else IoPin[16].In = 0;
if (b & 0x40) IoPin[17].In = 1; else IoPin[17].In = 0;
if (b & 0x80) IoPin[18].In = 1; else IoPin[18].In = 0;

b = octopus_io_get_port(&Octopus, 4); 
if (b & 0x01) IoPin[34].In = 1; else IoPin[34].In = 0;
if (b & 0x02) IoPin[35].In = 1; else IoPin[35].In = 0;
if (b & 0x04) IoPin[36].In = 1; else IoPin[36].In = 0;
if (b & 0x08) IoPin[37].In = 1; else IoPin[37].In = 0;
if (b & 0x20) IoPin[0].In = 1; else IoPin[0].In = 0;
if (b & 0x40) IoPin[1].In = 1; else IoPin[1].In = 0;
if (b & 0x80) IoPin[2].In = 1; else IoPin[2].In = 0;

b = octopus_io_get_port(&Octopus, 5);
if (b & 0x01) IoPin[33].In = 1; else IoPin[33].In = 0;
if (b & 0x02) IoPin[32].In = 1; else IoPin[32].In = 0;
if (b & 0x04) IoPin[31].In = 1; else IoPin[31].In = 0;
if (b & 0x08) IoPin[30].In = 1; else IoPin[30].In = 0;
if (b & 0x10) IoPin[29].In = 1; else IoPin[29].In = 0;
if (b & 0x20) IoPin[28].In = 1; else IoPin[28].In = 0;
if (b & 0x40) IoPin[27].In = 1; else IoPin[27].In = 0;
if (b & 0x80) IoPin[26].In = 1; else IoPin[26].In = 0;

for (i = 0; i < IO_PIN_COUNT; i++)
  {
  if ((IoPin[i].Mode > 2) && (IoPinDefs[i].Flags & PIN_A_IN))
    {
    if ((value = octopus_adc_get(&Octopus, IoPinDefs[i].Pin)) < 0)
      {
      msg_box(MSG_TYPE_ERROR, "Error", "ERROR (PIN:%u) octopus_adc_get: %s\n", IoPinDefs[i].Pin, Octopus.error_str);
      return(FALSE);
      }
    IoPin[i].AIn = value;
    }
  }

for (i = 0; i < IO_PIN_COUNT; i++)
  {
  if (IoPin[i].Mode == 0)
    {
    if (IoPin[i].InWidget)
      {
      if (IoPin[i].In)
        giw_led_set_mode(GIW_LED(IoPin[i].InWidget), 1);
      else
        giw_led_set_mode(GIW_LED(IoPin[i].InWidget), 0);    
      } 
    }
  else if (IoPin[i].Mode > 2)
    {
    if (IoPin[i].AInWidget)
      {
      if (IoPin[i].Mode == 3)
        g_snprintf(str, 20, "<b>%4u</b>", IoPin[i].AIn);      
      else if (IoPin[i].Mode == 4)
        g_snprintf(str, 20, "<b>%5d</b>", IoPin[i].AIn - IoPin[i+1].AIn);
      else
        strcpy(str, "<b>-</b>");      
      gtk_label_set_markup(GTK_LABEL(IoPin[i].AInWidget), str);
      }
    }
  }
return(TRUE);
}


GtkWidget *CreateMainWin(void)
{
gchar *filename;
unsigned int z, s;
GtkWidget *widget, *widget1, *widget2;
GtkObject *spinbutton_adj;
int i;

GtkWidget *window1;
GtkWidget *vbox1, *vbox2;
GtkWidget *menubar1;
GtkWidget *menuitem1;
GtkWidget *menuitem1_menu;
GtkWidget *open1;
GtkWidget *save1;
GtkWidget *beenden1;
GtkWidget *io1;
GtkWidget *io1_menu;
GtkWidget *alle_outputs_0;
GtkWidget *alle_outputs_1;
GtkWidget *separator1;
GtkWidget *config1;
GtkWidget *menuitem4;
GtkWidget *menuitem4_menu;
GtkWidget *about1;
GtkWidget *hseparator1;  
GtkWidget *image1;
GtkWidget *statusbar1;
GtkAccelGroup *accel_group;

accel_group = gtk_accel_group_new ();

window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window1), "Octopus-GUI");
gtk_window_set_position (GTK_WINDOW (window1), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (window1), FALSE);

vbox1 = gtk_vbox_new (FALSE, 0);
gtk_widget_show (vbox1);
gtk_container_add (GTK_CONTAINER (window1), vbox1);

menubar1 = gtk_menu_bar_new ();
gtk_widget_show (menubar1);
gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0);

menuitem1 = gtk_menu_item_new_with_mnemonic ("_File");
gtk_widget_show (menuitem1);
gtk_container_add (GTK_CONTAINER (menubar1), menuitem1);

menuitem1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem1), menuitem1_menu);

open1 = gtk_image_menu_item_new_from_stock ("gtk-open", accel_group);
gtk_widget_show (open1);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), open1);

save1 = gtk_image_menu_item_new_from_stock ("gtk-save", accel_group);
gtk_widget_show (save1);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), save1);

separator1 = gtk_separator_menu_item_new ();
gtk_widget_show (separator1);
gtk_container_add (GTK_CONTAINER(menuitem1_menu), separator1);
gtk_widget_set_sensitive (separator1, FALSE);

beenden1 = gtk_image_menu_item_new_from_stock ("gtk-quit", accel_group);
gtk_widget_show (beenden1);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), beenden1);

io1 = gtk_menu_item_new_with_mnemonic ("IO");
gtk_widget_show (io1);
gtk_container_add (GTK_CONTAINER (menubar1), io1);

io1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (io1), io1_menu);

alle_outputs_0 = gtk_menu_item_new_with_mnemonic ("Alle Outputs 0");
gtk_widget_show (alle_outputs_0);
gtk_container_add (GTK_CONTAINER (io1_menu), alle_outputs_0);

alle_outputs_1 = gtk_menu_item_new_with_mnemonic ("Alle Outputs 1");
gtk_widget_show (alle_outputs_1);
gtk_container_add (GTK_CONTAINER (io1_menu), alle_outputs_1);

separator1 = gtk_separator_menu_item_new ();
gtk_widget_show (separator1);
gtk_container_add (GTK_CONTAINER (io1_menu), separator1);
gtk_widget_set_sensitive (separator1, FALSE);

config1 = gtk_check_menu_item_new_with_mnemonic ("Config");
gtk_widget_show (config1);
gtk_container_add (GTK_CONTAINER (io1_menu), config1);


menuitem4 = gtk_menu_item_new_with_mnemonic ("_Help");
gtk_widget_show (menuitem4);
gtk_container_add (GTK_CONTAINER (menubar1), menuitem4);

menuitem4_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem4), menuitem4_menu);

about1 = gtk_menu_item_new_with_mnemonic ("_About");
gtk_widget_show (about1);
gtk_container_add (GTK_CONTAINER (menuitem4_menu), about1);

hseparator1 = gtk_hseparator_new ();
gtk_widget_show (hseparator1);
gtk_box_pack_start (GTK_BOX (vbox1), hseparator1, TRUE, TRUE, 4);

TableWdg = gtk_table_new (19, 3, FALSE);
gtk_widget_show(TableWdg);
gtk_box_pack_start (GTK_BOX (vbox1), TableWdg, TRUE, TRUE, 0);
gtk_table_set_row_spacings(GTK_TABLE(TableWdg), 2);

filename = CreateFileName(Paths.base_dir, "octopus_connect.png");
image1 = gtk_image_new_from_file(filename);
g_free(filename);
gtk_widget_show (image1);
gtk_table_attach (GTK_TABLE(TableWdg), image1, 1, 2, 0, 19,
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
gtk_misc_set_padding (GTK_MISC (image1), 10, 0);

for (i = 0; i < IO_PIN_COUNT; i++)
  {
  z = IoPinDefs[i].Zeile;
  s = IoPinDefs[i].Spalte;
  vbox2 = gtk_vbox_new(FALSE, 0);
  gtk_widget_show (vbox2);
  gtk_table_attach(GTK_TABLE(TableWdg), vbox2, s-1, s, z-1, z,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);
        
  if (IoPinDefs[i].Flags & PIN_IN)
    {
    // ** Input (Led)
    widget = gtk_hbox_new(FALSE, 5);
    gtk_widget_show (widget);
    gtk_box_pack_start(GTK_BOX(vbox2), widget, TRUE, TRUE, 0);
    IoPin[i].InBoxWidget = widget;
  
    widget = giw_led_new();
    gtk_widget_show (widget);
    gtk_box_pack_start(GTK_BOX(IoPin[i].InBoxWidget), widget, FALSE, FALSE, 0);
    IoPin[i].InWidget = widget;
    widget = gtk_label_new(IoPinDefs[i].InName);
    gtk_widget_show (widget);
    IoPin[i].InNameWidget = widget;
    gtk_box_pack_start(GTK_BOX(IoPin[i].InBoxWidget), widget, FALSE, FALSE, 0);
    }
  else
    {
    IoPin[i].InBoxWidget = NULL;
    IoPin[i].InWidget = NULL;
    IoPin[i].InNameWidget = NULL;
    }
  if (IoPinDefs[i].Flags & PIN_OUT)
    {
    // ** Output (Switch)
    widget = gtk_check_button_new_with_mnemonic(IoPinDefs[i].OutName);
    (void)g_signal_connect(widget, "toggled", G_CALLBACK(OutChangeProc), (gpointer)i); 
    //gtk_widget_show(widget);
    IoPin[i].OutWidget = widget;
    gtk_box_pack_start(GTK_BOX(vbox2), widget, FALSE, FALSE, 0);
    }
  else
    {
    IoPin[i].OutWidget = NULL;  
    }

  if (IoPinDefs[i].Flags & PIN_A_IN)
    {
    widget = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(vbox2), widget, TRUE, TRUE, 0);
    // Frame
    widget1 = gtk_frame_new (NULL); 
    gtk_widget_show (widget1);
    gtk_box_pack_start(GTK_BOX(widget), widget1, FALSE, FALSE, 0);
    gtk_frame_set_shadow_type(GTK_FRAME(widget1), GTK_SHADOW_ETCHED_OUT);
    // Label
    widget2 = gtk_label_new (" <b>0</b>");
    gtk_widget_show(widget2);
    gtk_container_add(GTK_CONTAINER(widget1), widget2);
    gtk_label_set_use_markup(GTK_LABEL(widget2), TRUE);
    gtk_misc_set_alignment(GTK_MISC(widget2), 0, 0.5);
    gtk_label_set_width_chars(GTK_LABEL(widget2), 7);      
    // Label
    widget1 = gtk_label_new(IoPinDefs[i].AnalogName);
    gtk_widget_show(widget1);
    gtk_box_pack_start(GTK_BOX(widget), widget1, FALSE, FALSE, 0);
    IoPin[i].AInNameWidget = widget1;
    IoPin[i].AInBoxWidget = widget;
    IoPin[i].AInWidget = widget2;
    }  
  else
    {
    IoPin[i].AInBoxWidget = NULL;
    IoPin[i].AInWidget = NULL;
    IoPin[i].AInNameWidget = NULL;
    }
  if (IoPinDefs[i].Flags & PIN_A_OUT)
    {
    widget = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(vbox2), widget, TRUE, TRUE, 0);
    
    spinbutton_adj = gtk_adjustment_new(0, 0, 255, 1, 10, 10);
    widget2 = gtk_spin_button_new(GTK_ADJUSTMENT(spinbutton_adj), 1, 0);
    gtk_widget_show (widget2);
    gtk_box_pack_start(GTK_BOX(widget), widget2, FALSE, FALSE, 0);
    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget2), TRUE);
    gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(widget2), GTK_UPDATE_IF_VALID);
    (void)g_signal_connect((gpointer)widget2, "value_changed", G_CALLBACK(AOutChangeProc), (gpointer)i);
    (void)g_signal_connect((gpointer)widget2, "activate", G_CALLBACK(AOutChangeProc), (gpointer)i);

    widget1 = gtk_label_new (IoPinDefs[i].AnalogName);
    gtk_widget_show (widget1);
    gtk_box_pack_start (GTK_BOX(widget), widget1, FALSE, FALSE, 0);
    IoPin[i].AOutNameWidget = widget1;
    IoPin[i].AOutBoxWidget = widget;
    IoPin[i].AOutWidget = widget2;
    }
  else
    {
    IoPin[i].AOutBoxWidget = NULL;
    IoPin[i].AOutWidget = NULL;
    IoPin[i].AOutNameWidget = NULL;
    }
  // ** Config
  widget = gtk_hbox_new (FALSE, 0);
  //gtk_widget_show (widget);
  gtk_box_pack_start(GTK_BOX(vbox2), widget, TRUE, TRUE, 0);
  IoPin[i].ConfigBoxWidget = widget;

  widget = gtk_combo_box_new_text();
  gtk_widget_show (widget);
  gtk_box_pack_start(GTK_BOX(IoPin[i].ConfigBoxWidget), widget, TRUE, TRUE, 0);
  if (IoPinDefs[i].Flags & PIN_IN)
    gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Input");
  if (IoPinDefs[i].Flags & PIN_OUT)
    gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Output"); 
  if (IoPinDefs[i].Flags & PIN_A_IN)
    gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Analog-In");
  if (IoPinDefs[i].Flags & PIN_A_OUT)
    gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Analog-Out");
  gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0);
  IoPin[i].ConfigWidget = widget;

  widget = gtk_label_new(IoPinDefs[i].CfgName);
  gtk_widget_show (widget);
  gtk_box_pack_start (GTK_BOX(IoPin[i].ConfigBoxWidget), widget, FALSE, FALSE, 0);

  widget = gtk_button_new_with_label("...");
  gtk_widget_show (widget);
  gtk_box_pack_start (GTK_BOX(IoPin[i].ConfigBoxWidget), widget, FALSE, FALSE, 0);
  (void)g_signal_connect(widget, "clicked", G_CALLBACK(OptionChangeCB), (gpointer)i);

  IoPin[i].Mode = 0;  
  }
//SetGuiShowing(0);

ExtraSetup.BoxWidget = gtk_hbox_new (FALSE, 0);
//gtk_widget_show (ExtraSetup.BoxWidget);
gtk_box_pack_start (GTK_BOX (vbox1), ExtraSetup.BoxWidget, TRUE, TRUE, 0);

// AD-Ref
widget = gtk_label_new ("Analog-Ref: ");
gtk_widget_show (widget);
gtk_box_pack_start(GTK_BOX(ExtraSetup.BoxWidget), widget, FALSE, FALSE, 0);

widget = gtk_combo_box_new_text ();
gtk_widget_show(widget);
gtk_box_pack_start(GTK_BOX(ExtraSetup.BoxWidget), widget, FALSE, FALSE, 0);
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "Ext. Ref");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "Int. 5V");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "Int. 2,56V");
gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0);
ExtraSetup.AdRefWidget = widget;

// PWM 1
widget = gtk_label_new ("   PWM1-Speed: ");
gtk_widget_show (widget);
gtk_box_pack_start(GTK_BOX(ExtraSetup.BoxWidget), widget, FALSE, FALSE, 0);

widget = gtk_combo_box_new_text();
gtk_widget_show(widget);
gtk_box_pack_start(GTK_BOX(ExtraSetup.BoxWidget), widget, FALSE, FALSE, 0);
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "System-clock 33kHz");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 8");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 64");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 256");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 1024");
gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0);
ExtraSetup.PwmSpeed1Widget = widget;
// PWM 2
widget = gtk_label_new ("   PWM2-Speed: ");
gtk_widget_show (widget);
gtk_box_pack_start(GTK_BOX(ExtraSetup.BoxWidget), widget, FALSE, FALSE, 0);

widget = gtk_combo_box_new_text();
gtk_widget_show(widget);
gtk_box_pack_start(GTK_BOX(ExtraSetup.BoxWidget), widget, FALSE, FALSE, 0);
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "external 32kHz");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "external / 8");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 32");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 64");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 128");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 256");
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), "/ 1024");
gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0);
ExtraSetup.PwmSpeed2Widget = widget;
  
statusbar1 = gtk_statusbar_new ();
gtk_widget_show (statusbar1);
gtk_box_pack_start (GTK_BOX (vbox1), statusbar1, FALSE, FALSE, 0);
gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar1), FALSE);

gtk_signal_connect(GTK_OBJECT(window1), "destroy", GTK_SIGNAL_FUNC(gtk_exit), NULL);
g_signal_connect ((gpointer) open1, "activate", G_CALLBACK(on_open_activate), NULL);
g_signal_connect ((gpointer) save1, "activate", G_CALLBACK(on_save_activate), NULL);
g_signal_connect ((gpointer) beenden1, "activate", G_CALLBACK (on_beenden1_activate), NULL);
g_signal_connect ((gpointer) alle_outputs_0, "activate", G_CALLBACK (on_alle_outputs_0_activate), NULL);
g_signal_connect ((gpointer) alle_outputs_1, "activate", G_CALLBACK (on_alle_outputs_1_activate), NULL);
g_signal_connect ((gpointer) config1, "activate", G_CALLBACK (on_config1_activate), NULL);
g_signal_connect ((gpointer) about1, "activate", G_CALLBACK (on_about1_activate), NULL);
  
gtk_window_add_accel_group (GTK_WINDOW(window1), accel_group);

return(window1);
}
